<!-- 
  select下拉框及多列选择组件                zls-2023/07/26
    所有属性、事件、方法、插槽，请参考       https://vant-contrib.gitee.io/vant/#/zh-CN/picker
    注意：select的级联选择器无法设置默认值!!!! 请使用Cascader（也就是columns不要使用树形结构的数据！）

  Attributes
    1、hasFather  是否存在关联的上级内容，上级不选，该项不可选，用于给出提示（默认为false）
    2、v-model 格式必须为{ text: '', value: ''/null }
  Events
    1、confirm    
    2、clear     

  Demo
    <Form ref="formRef">
      <z-select
        v-model="form.select1"
        label="select下拉框1"
        required
        :columns="columns1.list"
        :default-index="1"
        @clear="
          () => {
            form.select2.text = ''
            form.select2.value = ''
          }
        "
        :label-width="pxToRem(120)"
      ></z-select>
      <z-select v-model="form.select2" label="select下拉框2" required :disabled="!form.select1.value" hasFather :columns="columns1.list" :label-width="pxToRem(120)"></z-select>
      <z-select v-model="form.select3" label="select多列" :columns="columns2.list" :label-width="pxToRem(120)"></z-select>
      <z-select v-model="form.select4" label="select多列回选" :label-width="pxToRem(120)" :columns="columns24.list"></z-select>
    </Form>

    const form = reactive({
      select1: { text: '', value: '4' },
      select2: { text: '', value: '' },
      select3: { text: '', value: null },
      select4: { text: '', value: ['Tuesday', 'Evening', 'PlayGame'] }
    }) 

    const columns1 = reactive({
      list: [
        { text: '张三', value: '3' },
        { text: '李四', value: '4' },
        { text: '王五', value: '5' }
      ]
    })
    const columns2 = reactive({
      list: [
        // 第一列
        [
          { text: '周一', value: 'Monday' },
          { text: '周二', value: 'Tuesday' },
          { text: '周三', value: 'Wednesday' },
          { text: '周四', value: 'Thursday' },
          { text: '周五', value: 'Friday' }
        ],
        // 第二列
        [
          { text: '上午', value: 'Morning' },
          { text: '下午', value: 'Afternoon' },
          { text: '晚上', value: 'Evening' }
        ],
        // 第三列
        [
          { text: '吃饭', value: 'Eat' },
          { text: '学习', value: 'Study' },
          { text: '打游戏', value: 'PlayGame' }
        ]
      ]
    })
 -->
<template>
  <z-input v-bind="{ ...attrsFieldDefault, ...$attrs, modelValue: inputVal }" :rules="$attrs['required'] || $attrs['required'] === '' ? [{ required: true, message: '请选择' }] : []" @click="open">
    <template #right-icon>
      <z-svg name="chahao" v-if="inputVal" @click.stop="clear"></z-svg>
    </template>
  </z-input>
  <Popup v-model:show="show" v-bind="{ ...attrsPopupDefault, ...$attrs }" @click-overlay="show = false" @click-close-icon="show = false">
    <Picker
      v-model="selectedValues"
      :columns="$attrs['columns']"
      :columns-field-names="$attrs['columns-field-names']"
      :title="$attrs['title'] || '标题'"
      :loading="$attrs['loading']"
      :show-toolbar="$attrs['show-toolbar']"
      :default-index="$attrs['default-index']"
      :class="{ isCascader: isCascader }"
      @confirm="confirm"
      @cancel="show = false"
    />
  </Popup>
</template>

<script>
export default { name: 'z-select' }
</script>
<script setup>
import { Popup, Picker, showToast } from 'vant'
import { ref, useAttrs, watch } from 'vue'
import { getType } from '@/utils/index'
const emit = defineEmits(['update:modelValue', 'clear', 'confirm'])
const attrs = useAttrs()

const props = defineProps({
  hasFather: {
    type: Boolean,
    default: false
  }
})

// Field输入框默认属性
const attrsFieldDefault = {
  readonly: true,
  placeholder: '请选择',
  'is-link': true,
  maxlength: '2000'
}
// Popup弹框默认属性
const attrsPopupDefault = {
  position: 'bottom',
  round: true
}

const show = ref(false) // 是否显示弹框
const inputVal = ref('') // 输入框的值
const selectedValues = ref([]) // Piker组件的反选值
const isCascader = ref(attrs.columns && getType(attrs.columns[0]) === 'array' ? true : false) // 是否为多列选择器（需要它判断逻辑和改变样式）

watch(
  () => JSON.parse(JSON.stringify(attrs.modelValue)),
  (newVal, oldVal) => {
    inputVal.value = newVal.text
    // 计算Piker组件的反选值
    if (!newVal.value) {
      selectedValues.value = []
      return
    }
    if (isCascader.value) {
      selectedValues.value = newVal.value
      return
    }
    selectedValues.value = [newVal.value]
  },
  { immediate: true }
)

// 当有默认值时，回选
const textArr = []
setDefaultValue(attrs.modelValue.value)
function setDefaultValue(values) {
  if (!values) return
  if (getType(values) === 'array') {
    attrs.columns.forEach(child => {
      child.forEach(v => {
        if (values.includes(v.value)) {
          textArr.push(v.text)
        }
      })
    })
    emit('update:modelValue', { text: textArr.join(','), value: values })
  } else {
    const obj = attrs.columns.find(v => v.value === values)
    emit('update:modelValue', { text: obj.text, value: values })
  }
}

function open() {
  if (attrs.disabled && props.hasFather) {
    showToast('请选择上级内容')
    return
  }
  show.value = true
}

// 清空
function clear() {
  const data = isCascader.value ? { text: '', value: null } : { text: '', value: '' }
  emit('update:modelValue', data)
  emit('clear', data)
}

// 选中某一项后，点击确认按钮
function confirm({ selectedOptions }) {
  show.value = false
  let valueArr = [],
    textArr = []
  selectedOptions.forEach(v => {
    valueArr.push(v.value)
    textArr.push(v.text)
  })
  emit('update:modelValue', { text: textArr.join(), value: isCascader.value ? valueArr : valueArr.join() })
}
</script>
